package com.xwj.juc.threadPool;

import java.util.HashSet;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author xwj
 * @date 2020/4/28
 */
public class DefaultThreadPool<Job extends Runnable> implements ThreadPool<Job> {
    /**
     * 线程池最大工作者线程数
     */
    private static final int MAX_WORKER_NUMBERS = 10;
    /**
     * 线程池核心工作线程数
     */
    private static final int CORE_WORKER_NUMBERS = 5;
    /**
     * 线程池默认工作线程数
     */
    private static final int DEFAULT_WORKER_NUMBERS = 5;
    /**
     * 工作队列
     */
    private final LinkedBlockingQueue<Job> workQueue = new LinkedBlockingQueue<>();
    /**
     * 工作列表
     */
    private final CopyOnWriteArrayList<Worker> workers = new CopyOnWriteArrayList<>();
    /**
     * 工作者线程数量
     */
    private AtomicInteger workNum = new AtomicInteger(DEFAULT_WORKER_NUMBERS);
    /**
     * 线程编号
     */
    private AtomicInteger threadNum = new AtomicInteger();

    public DefaultThreadPool() {
        initWorkers(DEFAULT_WORKER_NUMBERS);
    }

    public DefaultThreadPool(int num) {
        int realNum = num > MAX_WORKER_NUMBERS ? MAX_WORKER_NUMBERS : num < CORE_WORKER_NUMBERS ? CORE_WORKER_NUMBERS : num;
        workNum.compareAndSet(DEFAULT_WORKER_NUMBERS, realNum);
        initWorkers(workNum.get());
    }

    @Override
    public void execute(Job job) {
        if(job != null) {
            workQueue.offer(job);
        }
    }

    @Override
    public void shutDown() {
        for(Worker worker : workers) {
            worker.shutDown();
        }
    }

    @Override
    public void addWorker(int num) {
        for(;;) {

        }
    }

    @Override
    public void removeWorker(int num) {

    }

    @Override
    public int getJobSize() {
        return workers.size();
    }

    private void initWorkers(int num) {
        for (int i = 0; i < num; i++) {
            Worker worker = new Worker();
            workers.add(worker);
            Thread thread = new Thread(worker, "Thread-pool-" + threadNum.incrementAndGet());
            thread.start();
        }
    }

    class Worker implements Runnable {
        private volatile boolean isRunning = true;

        @Override
        public void run() {
            while (isRunning) {
                Job job = null;
                try {
                    job = workQueue.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (job != null) {
                    try {
                        job.run();
                    } catch (Exception e) {

                    }

                }
            }
        }

        public void shutDown() {
            isRunning = false;
        }
    }
}
